import threading
import time

import pyperclip
from PySide6.QtCore import QThread, Signal, Slot
from pynput import keyboard

from .config import Settings
from .log import logger
from .trans import Baidu, Youdao, Language


class ClipboardMonitor(QThread):
    set_trans_clipboard = Signal(str)

    def __init__(self, app, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.app = app

        # 表示线程阻塞的标志位
        self.__enable = threading.Event()
        self.__enable.set()
        # 表示线程是否正在运行
        self.__running = threading.Event()
        self.__running.set()

        self.__cur_text = ''

        self.settings = Settings()
        self.baidu = Baidu()
        self.youdao = Youdao()

    def connect_slots(self):
        self.set_trans_clipboard.connect(self.app.main_window.set_trans_clipboard_handler)

    def run(self) -> None:
        while self.__running.is_set():
            self.__enable.wait()
            clipboard_content = next(self.read_clipboard())  # 获取剪贴板内容

            if clipboard_content:
                logger.debug(f'Clipboard content: {clipboard_content}')
                format_text = self.format_clipboard(clipboard_content)
                trans_text = self.translate_clipboard(format_text)
                logger.debug(f'Translated text: {trans_text}')
                self.set_trans_clipboard.emit(trans_text)

    def quit(self):
        super().quit()
        self.__enable.set()
        self.__running.clear()
        logger.debug('Clipboard monitor quit')

    @property
    def enable(self) -> bool:
        return self.__enable.is_set()

    @enable.setter
    def enable(self, value):
        if value:
            self.__enable.set()
            logger.debug('Clipboard monitor enabled')
        else:
            self.__enable.clear()
            logger.debug('Clipboard monitor disabled')

    @Slot(bool)
    def set_enable_handler(self, enable: bool):
        logger.debug(f'Handle set_enable, enable={enable}')
        self.enable = enable

    def read_clipboard(self):
        while True:
            time.sleep(0.1)

            try:
                text = pyperclip.paste()
            except pyperclip.PyperclipWindowsException:
                logger.warning('Unable to access the clipboard while system is sleeping')
                continue

            if isinstance(text, str) and text != self.__cur_text:
                self.__cur_text = text
                yield text
            else:
                yield None

    def translate_clipboard(self, text):
        if self.settings.trans_api == 'Baidu':
            return self.baidu_translate(text, self.settings.trans_mode)
        elif self.settings.trans_api == 'Youdao':
            return self.youdao_translate(text, self.settings.trans_mode)
        else:
            logger.exception(f'Invalid trans API, trans_api={self.settings.trans_api}')
            return ''

    def baidu_translate(self, text, trans_mode):
        if trans_mode == 'auto':
            from_lang, to_lang = 'auto', 'zh'
        elif trans_mode == 'zh_en':
            lang = Language.detect(text, Language.zh_cn, Language.en)
            from_lang, to_lang = ('zh', 'en') if lang == Language.zh_cn else ('en', 'zh')
        elif trans_mode == 'zh_jp':
            lang = Language.detect(text, Language.zh_cn, Language.ja)
            from_lang, to_lang = ('zh', 'jp') if lang == Language.zh_cn else ('jp', 'zh')
        else:
            logger.exception(f'Invalid trans mode, trans_mode={trans_mode}')
            return ''

        return self.baidu.translate(text, from_lang, to_lang)

    def youdao_translate(self, text, trans_mode):
        if trans_mode == 'auto':
            from_lang, to_lang = 'auto', 'zh-CHS'
        elif trans_mode == 'zh_en':
            lang = Language.detect(text, Language.zh_cn, Language.en)
            from_lang, to_lang = ('zh-CHS', 'en') if lang == Language.zh_cn else ('en', 'zh-CHS')
        elif trans_mode == 'zh_jp':
            lang = Language.detect(text, Language.zh_cn, Language.ja)
            from_lang, to_lang = ('zh-CHS', 'ja') if lang == Language.zh_cn else ('ja', 'zh-CHS')
        else:
            logger.exception(f'Invalid trans mode, trans_mode={trans_mode}')
            return ''

        return self.youdao.translate(text, from_lang, to_lang, self.settings.youdao_domain,
                                     self.settings.youdao_reject_fallback)

    @staticmethod
    def format_clipboard(text):
        # 去掉断行符号
        text = text.replace('\n', ' ')
        # 去掉因断行产生的连字符
        text = text.replace('- ', '')
        text = text.replace(' -', '')
        # 去掉多余的空格
        text = ' '.join(text.split())

        return text


class GlobalHotKeysManager(QThread):
    # text_updated = Signal(str)
    # set_show_hide = Signal()
    set_pos = Signal(str)
    set_on_listening = Signal(bool)
    set_show_mode = Signal(str)

    def __init__(self, app, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.app = app
        self.settings = Settings()

        self.show_mode_hot_key = '<ctrl>+<alt>+h'
        self.enable_hot_key = '<ctrl>+<alt>+l'
        self.up_hot_key = '<ctrl>+<alt>+1'
        self.down_hot_key = '<ctrl>+<alt>+2'
        self.left_hot_key = '<ctrl>+<alt>+3'
        self.right_hot_key = '<ctrl>+<alt>+4'

        self.youdao = Youdao()
        self.baidu = Baidu()

        self.global_hot_keys = keyboard.GlobalHotKeys({
            self.show_mode_hot_key: self.on_activate_show_mode,
            self.enable_hot_key: self.on_activate_enable,
            self.up_hot_key: self.on_activate_up,
            self.down_hot_key: self.on_activate_down,
            self.left_hot_key: self.on_activate_left,
            self.right_hot_key: self.on_activate_right,
        })

    def connect_slots(self):
        self.set_show_mode.connect(self.app.main_window.set_shrink_expand_handler)
        self.set_pos.connect(self.app.main_window.set_pos_handler)
        self.set_pos.connect(self.app.settings_window.tab_appearance.set_pos_handler)
        self.set_on_listening.connect(self.app.clipboard_monitor.set_enable_handler)

    def run(self):
        self.global_hot_keys.daemon = True
        self.global_hot_keys.start()
        logger.debug('Global hot keys started')

    def quit(self):
        super().quit()
        self.global_hot_keys.stop()
        logger.debug('Global hot keys stopped')

    def on_activate_show_mode(self):
        logger.debug(f'{self.show_mode_hot_key} pressed')
        self.set_show_mode.emit(self.settings.pos)

    def on_activate_enable(self):
        logger.debug(f'{self.enable_hot_key} pressed')
        self.app.clipboard_monitor.enable ^= True
        enable = self.app.clipboard_monitor.enable
        self.set_on_listening.emit(enable)

    def on_activate_up(self):
        logger.debug(f'{self.up_hot_key} pressed')
        self.settings.pos = 'up'
        self.set_pos.emit('up')

    def on_activate_down(self):
        logger.debug(f'{self.down_hot_key} pressed')
        self.settings.pos = 'down'
        self.set_pos.emit('down')

    def on_activate_left(self):
        logger.debug(f'{self.left_hot_key} pressed')
        self.settings.pos = 'left'
        self.set_pos.emit('left')

    def on_activate_right(self):
        logger.debug(f'{self.right_hot_key} pressed')
        self.settings.pos = 'right'
        self.set_pos.emit('right')
